﻿using Microsoft.Office.InfoPath;
using System;
using System.IO;
using System.Text.RegularExpressions;

namespace InfoPathHelpers.Validation
{
    /// <summary>
    /// Provides a number of methods for validating different data types.
    /// Note: These methods should only be called from a validation event.
    /// </summary>
    public static partial class ValidationHelper
    {
        /// <summary>
        /// Provides validation of the characters in a string.
        /// </summary>
        /// <param name="invalidChars">An array of characters not allowed in the field.</param>
        /// <param name="eventArgs">The XmlValidatingEventArgs of the validation event</param>
        /// <returns>True if the field did not contain any invalid characters; otherwise false.</returns>
        public static bool HasInvalidCharacters(XmlValidatingEventArgs eventArgs, char[] invalidChars)
        {
            return HasInvalidCharacters(eventArgs, invalidChars, false, false);
        }

        /// <summary>
        /// Provides validation of the characters in a string
        /// with the option to show dialog to the user for failures.
        /// </summary>
        /// <param name="invalidChars">An array of characters not allowed in the field.</param>
        /// <param name="eventArgs">The XmlValidatingEventArgs of the validation event</param>
        /// <param name="allowBlanks">A boolean value indicating whether or not the field can be empty.</param>
        /// <param name="showDialog">A boolean value indicating whether or not to show the user a message on validation failure.</param>
        /// <returns>True if the field did not contain any invalid characters; otherwise false.</returns>
        public static bool HasInvalidCharacters(XmlValidatingEventArgs eventArgs, char[] invalidChars, bool allowBlanks, bool showDialog)
        {
            return HasInvalidCharacters(eventArgs, invalidChars, allowBlanks, showDialog,
                new ValidationMessage()
                {
                    Caption = "Invalid Entry",
                    Message = "Invalid characters entered.",
                    MessageDetails = "This field cannot contain any of the following chars:\r\n\r\n" +
                       GetStringFromCharacters(invalidChars) + "."
                },
                new ValidationMessage()
                {
                    Caption = "Blank Entry",
                    Message = "Cannot be blank.",
                    MessageDetails = "This field must have a value."
                }
            );
        }

        /// <summary>
        /// Provides validation of the characters in a string
        /// with the option to show a custom dialog to the user for failures.
        /// </summary>
        /// <param name="invalidChars">An array of characters not allowed in the field.</param>
        /// <param name="eventArgs">The XmlValidatingEventArgs of the validation event</param>
        /// <param name="allowBlanks">A boolean value indicating whether or not the field can be empty.</param>
        /// <param name="showDialog">A boolean value indicating whether or not to show the user a message on validation failure.</param>
        /// <returns>True if the field contained a valid email address; otherwise false.</returns>
        /// <param name="blankMessage">The message to show for blank fields if not allowed.</param>
        /// <param name="invalidMessage">The message to show for fields containing invalid characters.</param>
        /// <returns>True if the field did not contain any invalid characters; otherwise false.</returns>
        public static bool HasInvalidCharacters(XmlValidatingEventArgs eventArgs, char[] invalidChars, bool allowBlanks, bool showDialog, ValidationMessage invalidMessage, ValidationMessage blankMessage)
        {
            if (eventArgs.Operation == XmlOperation.Delete || eventArgs.Operation == XmlOperation.None)
                // Delete operations or unspecififed operations are not validated so just return true.
                return true;

            // Insert operations do not use the New/OldValue parameters of XmlValidatingEventArgs
            // so we need to use the Value of the underlying xml element.
            string Value = eventArgs.Site.Value;

            bool IsEmpty = string.IsNullOrEmpty(Value);
            bool HasInvalidCharachters = Value.IndexOfAny(invalidChars).Equals(-1);

            if (!IsEmpty && !HasInvalidCharachters)
            {
                // If the field is not empty and the value is not a valid email address then validation has failed.
                // So we report failure using "invalidMessage".
                HandleValidationFailure(eventArgs, invalidMessage, showDialog);
                // And of course return false because validation failed.
                return true;
            }
            else if (IsEmpty && !allowBlanks)
            {
                // If the value is empty but validation does not allow blanks then validation fails.
                // So we report failure using the "blankMessage".
                HandleValidationFailure(eventArgs, blankMessage, showDialog);
                // And of course return false because validation failed.
                return true;
            }

            // Otherwise either the field is empty or a valid email addresss so validation succeeded.
            return false;
        }

        private static string GetStringFromCharacters(char[] inputChars)
        {
            System.Text.StringBuilder OutputString = new System.Text.StringBuilder();
            Array.ForEach(inputChars, delegate(char c)
            {
                if (!c.Equals(0))
                {
                    OutputString.Append(c + " ");
                }
            });
            return OutputString.ToString().Trim();
        }
    }
}
